%{
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "symtab.h"
#include "tree.h"
#include "codegen.h"
  extern int lexeme, line;
struct tree * too;
%}

%union {
  int intval;
  char *name;
  char *code;
  struct tree *treep;
}

%token INT STATIC VOID
%token IF WHILE ELSE RETURN EXIT READ
%token <intval> ENTIER
%token <name> ID
%token END 0 "end of file"

 //%type OU ET '<' '>' INF_EG SUP_EG MOINS_UNAIRE
%type <treep> expr
%type <code> instruction

%left ','
%right '='
%left OU
%left ET
%left EGAL DIF 
%left '<' '>' INF_EG SUP_EG
%left '+' '-'
%left '*' '/' '%' 
%right '!' MOINS_UNAIRE
%left '(' '['

%expect 1 // Conflit if-else : décalage accepté par défaut

%error-verbose

%%


prog : debut
;

debut : declaration debut
      | prototype ';' debut
      | error debut { yyerrok; }
      | fonction l_fonctions
;

declaration : INT ID ';' //{ ajouterSymbole($2); }
            | INT ID '[' ENTIER ']' ';'
            | STATIC INT ID ';'
            | STATIC INT ID '[' ENTIER ']' ';'
;

prototype : VOID ID '(' VOID ')'
          | VOID ID '(' liste_types ')'
          | INT ID '(' VOID ')'
          | INT ID '(' liste_types ')'
;

liste_types : INT 
            | INT ',' liste_types
;

fonction : en_tete '{' corps '}'
         | error '{' corps '}' { yyerrok; }
;

l_fonctions : /* Empty */
            | fonction l_fonctions
;

en_tete : VOID ID '(' VOID ')'
        | VOID ID '(' liste_param ')' 
        | INT ID '(' VOID ')'
        | INT ID '(' liste_param ')'
;

liste_param : param
            | param ',' liste_param
;

param : INT ID
      | INT ID '[' ENTIER ']'
;

corps : declaration corps
      | error declaration corps { yyerrok; }
      |	l_instructions
;

l_instructions : /* Empty */
               | instruction l_instructions { dump($1); }
               | error l_instructions { yyerrok; }
;

/* Changer la grammaire pour gérer correctement les ; */
instruction : ID '=' expr ';' { $$ = "a"; }
            | ID '[' expr ']' '=' expr ';'{ $$ = "a"; }
            | EXIT '(' ENTIER ')' ';'{ $$ = "a"; }
            | RETURN expr ';'{ $$ = "a"; }
            | RETURN ';'{ $$ = "a"; }
            | READ '(' ID ')' ';'{ $$ = "a"; }
            | IF '(' expr ')' instruction { compute_height($3); 
                                            dump(gen_if(gen_expr($3, 1), $5)); }
            | IF '(' expr ')' instruction ELSE instruction{ $$ = "a"; }
            | WHILE '(' expr ')' instruction{ $$ = "a"; }
            | '{' l_instructions '}'{ $$ = "a"; }
| expr ';' { compute_height($1); display_tree($1, 1); $$ = gen_expr($1, 1); }
;

expr : expr '+' expr { $$ = build_tree(PLUS, $1, $3); }
     | expr '-' expr { $$ = build_tree(MOINS, $1, $3); }
     | expr '*' expr { $$ = build_tree(FOIS, $1, $3); }
     | expr '/' expr { $$ = build_tree(DIVISE, $1, $3); }
     | expr '%' expr { $$ = build_tree(MODULO, $1, $3); }
     | expr '<' expr { $$ = build_tree(INF, $1, $3); }
     | expr '>' expr { $$ = build_tree(SUP, $1, $3); }
     | expr INF_EG expr { $$ = build_tree(INF_EG, $1, $3); }
     | expr SUP_EG expr { $$ = build_tree(SUP_EG, $1, $3); }
     | expr DIF expr { $$ = build_tree(DIF, $1, $3); }
     | expr EGAL expr { $$ = build_tree(EGAL, $1, $3); }
     | expr ET expr { $$ = build_tree(ET, $1, $3); }
     | expr OU expr { $$ = build_tree(OU, $1, $3); }
     | '-' expr %prec MOINS_UNAIRE { $$ = build_tree(MOINS_UNAIRE, $2, NULL); }
     | '!' expr { $$ = build_tree(NOT, $2, NULL); }
     | '(' expr ')' { $$ = $2; }
     | ID { $$ = create_id(ID, $1); }
     | ID '(' suite_argum ')' { $$ = create_id(ID, $1); /* A changer */ }
     | ID '[' expr ']' { $$ = create_id(ID, $1); /* A changer */ }
     | ENTIER { $$ = create_int(ENTIER, $1); }
;

suite_argum : /* Empty */
            | liste_argum
;

liste_argum : expr
            | expr ',' liste_argum
;

%%

yyerror(char *message)
{
  printf("\n******** ERROR ********\n\nLigne %d, lexeme %d :\n%s\n", line, lexeme, message);
}

int main(int argc, char *argv[])
{
  //creer_dico();
  //yydebug = 1;
  if(yyparse() == 0)
    printf("\nAnalyse terminee\n");
  return(0);
}
 
